﻿using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.GameAOT;
using UnityEngine;
using UnityEngine.EventSystems;
using Object = UnityEngine.Object;

namespace IQIGame.Onigao.GamePlay
{
    public static class BattleClientUtil
    {
        public static bool IsEditorMode
        {
            get
            {
#if UNITY_EDITOR
                if (!Application.isPlaying && SkillEditorMainUpdate.Instance)
                {
                    return true;
                }
                else
#endif
                {
                    return false;
                }
            }
        }

        public static GameObject CreateGameobject(GameObject rPrefab, Transform rParnet = null, string rName = null)
        {
            GameObject rGo = null;
            if (rParnet)
            {
                rGo = rPrefab.Instantiate(rParnet);
            }
            else
            {
                rGo = rPrefab.Instantiate();
            }

            if (!string.IsNullOrEmpty(rName))
            {
                rGo.name = rName;
            }

            return rGo;
        }

        public static void SafeDestroy(Object rObj)
        {
            if (rObj)
            {
                UnityExtension.SafeDestroy(rObj);
            }
        }

        public static string GetHitEffectNameByDamageType(EDamageType rType)
        {
            var rEffectName = string.Empty;
            switch (rType)
            {
                case EDamageType.Physical:
                    rEffectName = "FX_Hit_Physics";
                    break;
                case EDamageType.Magic:
                    rEffectName = "FX_Hit_Magic";
                    break;
                case EDamageType.Ice:
                    rEffectName = "FX_Hit_Ice";
                    break;
                case EDamageType.Electricity:
                    rEffectName = "FX_Hit_Light";
                    break;
                case EDamageType.Fire:
                    rEffectName = "FX_Hit_Fire";
                    break;
                default:
                    rEffectName = "FX_Hit_Physics";
                    break;
            }
            return rEffectName;
        }

        public static Vector3 ScreenDirToWorld(Quaternion cameraRot, Vector2 dir)
        {
            var rMoveDir = Vector3.zero;
            if (dir != Vector2.zero)
            {
                rMoveDir = cameraRot * Vector3.forward * dir.y + cameraRot * Vector3.right * dir.x;
                rMoveDir.y = 0;
            }
            return rMoveDir;
        }

        public static void SetEntityDriverToUnitView(EntityDriver rDriver, UnitView rUnitView)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                BattleData.editorDriver[rDriver] = rUnitView;
            }
            else
#endif
            {
                BattleManager.Instance.ctrl.data.SetDriverToUnit(rDriver, rUnitView);
            }
        }

        public static UnitView GetUnitViewByEntityDriver(EntityDriver rDriver)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                if (BattleData.editorDriver.TryGetValue(rDriver, out var rUnitView))
                {
                    return rUnitView;
                }
            }
            else
#endif
            {
                if (BattleManager.Instance.ctrl != null && BattleManager.Instance.ctrl.data.TryGetUnitByDriver(rDriver, out var rUnitView))
                {
                    return rUnitView;
                }
            }
            return null;
        }

        /// <summary>
        /// 对v3做rot相对与forward相同绕Y轴的旋转
        /// </summary>
        /// <param name="v3"></param>
        /// <param name="rot"></param>
        /// <returns></returns>
        public static Vector3 Vector3Rotate(Vector3 v3, Vector3 rot)
        {
            rot.y = 0;
            var fAngle = Mathf.Acos(Vector3.Dot(rot.normalized, Vector3.forward)) * 180 / Mathf.PI;
            if (rot.x < 0)
            {
                fAngle = 360 - fAngle;
            }
            var q = Quaternion.AngleAxis(fAngle, Vector3.up);
            var rNew = q * v3;
            return rNew;
        }

        public static async UniTaskVoid DelayInvoke(int nTime, Action rAction, CancellationToken cancellationToken = default(CancellationToken))
        {
            await UniTask.Delay(nTime, cancellationToken: cancellationToken);
            rAction?.Invoke();
        }
    }
}